﻿using System.Globalization;
using System.IO;

namespace XYAC.Framework.MonitorTireMaterialManual.DataExporter
{
    public enum Section
    {
        None,
        Points,
        MeasureKeys,
        TypeName,
        ID,
        XReference,
        Keys
    }
    /// <summary>
    /// 沃华离线软件检测数据解析器。
    /// 
    ///胎面总面积计算步骤：
    ///STEP1:获取各个扫描点之间的间隔长度
    ///读取TXT文档第一行，即可获取各点间隔长度
    ///STEP2:计算中心点位置序号
    ///mid = round([XReference] / 0.03200341)
    ///STEP3:计算左面积测量值
    ///从序号1至mid，使用公式S左 =Σ((厚度n+厚度n-1)*0.03200341/2)
    ///STEP4:计算右面积实际值
    ///从序号mid+1至末尾，使用公式S右 =Σ((厚度n+厚度n-1)*0.03200341/2)
    ///STEP5:计算总面积
    ///总面积 = S左 + S右
    /// </summary>
    public class DataFileParser
    {
        /// <summary>
        /// 记录行号（位置标记）。
        /// 另外：假定：由于解析器是逐行进行处理的，所以他们的位置标号是可以作为数据的索引位置的。
        /// </summary>
        static int MeasureKeyIndex = 0;

        public static DataFile LoadFromFile(string filePath)
        {
            try
            {
                if (!File.Exists(filePath))
                    throw new FileNotFoundException($"文件未找到: {filePath}");

                DataFile dataFile = new DataFile();
                Section currentSection = Section.None;
                MeasureKeyIndex = 0;

                using (StreamReader reader = new StreamReader(filePath))
                {
                    string line;
                    bool isFirstLine = true;

                    while ((line = reader.ReadLine()) != null)
                    {
                        line = line.Trim();

                        // 跳过空行
                        if (string.IsNullOrEmpty(line))
                            continue;

                        // 检查是否为段落标题
                        if (line.StartsWith("[") && line.EndsWith("]"))
                        {
                            string sectionName = line.Substring(1, line.Length - 2);
                            switch (sectionName)
                            {
                                case "MeasureKeys":
                                    currentSection = Section.MeasureKeys;
                                    break;
                                case "TypeName":
                                    currentSection = Section.TypeName;
                                    break;
                                case "ID":
                                    currentSection = Section.ID;
                                    break;
                                case "XReference":
                                    currentSection = Section.XReference;
                                    break;
                                case "Keys":
                                    currentSection = Section.Keys;
                                    break;
                                default:
                                    currentSection = Section.None;
                                    break;
                            }
                            continue;
                        }

                        // 解析内容
                        switch (currentSection)
                        {
                            case Section.None:
                                if (isFirstLine)
                                {
                                    // 第一行是 FileInertiaWidth
                                    if (float.TryParse(line, NumberStyles.Any, CultureInfo.InvariantCulture, out float inertiaWidth))
                                    {
                                        dataFile.FileInertvaWidth = inertiaWidth;
                                    }
                                    else
                                    {
                                        throw new FormatException("无法解析 FileInertiaWidth");
                                    }
                                    isFirstLine = false;
                                }
                                else
                                {
                                    // 默认认为是 [Points] 区域
                                    if (line.StartsWith("[Points]"))
                                    {
                                        currentSection = Section.Points;
                                        continue;
                                    }

                                    // 或者直接从第二行开始默认为 [Points]
                                    currentSection = Section.Points;
                                    // 继续处理当前行作为 Points
                                }
                                goto case Section.Points;

                            case Section.Points:
                                // 解析 Points 数据，格式: Index\tValue1\tValue2
                                var pointParts = line.Split(new[] { '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                                if (pointParts.Length >= 3)
                                {
                                    if (int.TryParse(pointParts[0], out int index) &&
                                        float.TryParse(pointParts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out float val1) &&
                                        float.TryParse(pointParts[2], NumberStyles.Any, CultureInfo.InvariantCulture, out float val2))
                                    {
                                        dataFile.Points.Add(new Point
                                        {
                                            Index = index,
                                            X = val1,
                                            Y = val2
                                        });
                                    }
                                    else
                                    {
                                        throw new FormatException($"无法解析 Points 行: {line}");
                                    }
                                }
                                break;

                            case Section.MeasureKeys:
                                // 解析 MeasureKeys 数据，格式: Coordinate\tValue
                                MeasureKeyIndex++;
                                var measureParts = line.Split(new[] { '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                                if (measureParts.Length >= 2)
                                {
                                    if (double.TryParse(measureParts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out double mCoord) &&
                                        double.TryParse(measureParts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out double mValue))
                                    {
                                        dataFile.MeasureKeys.Add(new MeasureKey
                                        {
                                            Index = MeasureKeyIndex,
                                            Coordinate = mCoord,
                                            Value = mValue
                                        });
                                    }
                                    else
                                    {
                                        throw new FormatException($"无法解析 MeasureKeys 行: {line}");
                                    }
                                }
                                break;

                            case Section.TypeName:
                                // 解析 TypeName，假设 TypeName 只有一行
                                dataFile.TypeName = line;
                                currentSection = Section.None;
                                break;

                            case Section.ID:
                                // 解析 ID，假设 ID 只有一行
                                if (int.TryParse(line, out int id))
                                {
                                    dataFile.ID = id;
                                }
                                else
                                {
                                    throw new FormatException("无法解析 ID");
                                }
                                currentSection = Section.None;
                                break;

                            case Section.XReference:
                                // 解析 XReference，假设 XReference 只有一行
                                if (double.TryParse(line, NumberStyles.Any, CultureInfo.InvariantCulture, out double xRef))
                                {
                                    dataFile.XReference = xRef;
                                }
                                else
                                {
                                    throw new FormatException("无法解析 XReference");
                                }
                                currentSection = Section.None;
                                break;

                            case Section.Keys:
                                // 解析 Keys 数据，格式: Coordinate\tValue
                                var keyParts = line.Split(new[] { '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                                if (keyParts.Length >= 2)
                                {
                                    if (double.TryParse(keyParts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out double kCoord) &&
                                        double.TryParse(keyParts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out double kValue))
                                    {
                                        dataFile.StableKeys.Add(new StableKeys
                                        {
                                            Coordinate = kCoord,
                                            Value = kValue
                                        });
                                    }
                                    else
                                    {
                                        throw new FormatException($"无法解析 Keys 行: {line}");
                                    }
                                }
                                break;

                            default:
                                // 未知部分，忽略或处理其他部分
                                break;
                        }
                    }
                }

                var leftArea = LeftArea(dataFile);

                var rightArea = RightArea(dataFile);

                var leftMeasureArea = LeftMeasureArea_new(dataFile);// LeftMeasureArea(dataFile);
                var rightMeasureArea = RightMeasureArea_new(dataFile);// RightMeasureArea(dataFile);

                dataFile.LeftArea = leftArea;
                dataFile.RightArea = rightArea;
                dataFile.Area = leftArea + rightArea;

                dataFile.MeasureLeftArea = leftMeasureArea;
                dataFile.MeasureRightArea = rightMeasureArea;
                dataFile.MeasureArea = leftMeasureArea + rightMeasureArea;

                dataFile.SideLeftWidth = caclSideLeftWidth(dataFile);
                dataFile.SideRightWidth = caclSideRightWidth(dataFile);
                dataFile.SideLeftWidthInfact = (float)dataFile.XReference;
                dataFile.SideRightWidthInfact = (float)dataFile.MeasureKeys.LastOrDefault().Coordinate;

                return dataFile;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            return null;
        }


        /// <summary>
        /// 边缘端点厚度(mm)=MeasureKeys第1组第2位
        /// </summary>
        /// <returns></returns>
        private static float endThick(DataFile dataFile)
        {
            return (float)dataFile.MeasureKeys[0].Value;
        }

        private static float caclSideLeftWidth(DataFile dataFile)
        {
            var pos = (int)(dataFile.StableKeys.Count / 2);
            return (float)dataFile.StableKeys[pos].Coordinate;
        }

        private static float caclSideRightWidth(DataFile dataFile)
        {
            var pos = (int)(dataFile.StableKeys.Count / 2);
            return (float)dataFile.StableKeys[pos].Value;
        }

        /// <summary>
        /// 获取轮廓左侧面积（[Keys]）。
        /// </summary>
        private static float LeftArea(DataFile dataFile)
        {
            var m_XReference = dataFile.XReference;
            double num = 0f;
            for (int i = 0; i < (dataFile.StableKeys.Count - 1); i++)
            {
                if ((dataFile.StableKeys[i].Coordinate < m_XReference) && (dataFile.StableKeys[i + 1].Coordinate <= m_XReference))
                {
                    num += ((dataFile.StableKeys[i].Value + dataFile.StableKeys[i + 1].Value) * (dataFile.StableKeys[i + 1].Coordinate - dataFile.StableKeys[i].Coordinate)) / 2f;
                }
                else if ((dataFile.StableKeys[i].Coordinate < m_XReference) && (dataFile.StableKeys[i + 1].Coordinate > m_XReference))
                {
                    num += ((dataFile.StableKeys[i].Value + GetStableLineY(dataFile.StableKeys, m_XReference)) * (m_XReference - dataFile.StableKeys[i].Coordinate)) / 2f;
                }
            }
            return (float)num;
        }

        /// <summary>
        /// 获取轮廓右侧面积（[Keys]）。
        /// </summary>
        private static float RightArea(DataFile dataFile)
        {
            var m_XReference = dataFile.XReference;
            double num = 0f;
            for (int i = 0; i < (dataFile.StableKeys.Count - 1); i++)
            {
                if ((dataFile.StableKeys[i].Coordinate <= m_XReference) && (dataFile.StableKeys[i + 1].Coordinate > m_XReference))
                {
                    num += ((dataFile.StableKeys[i + 1].Value + GetStableLineY(dataFile.StableKeys, m_XReference)) * (dataFile.StableKeys[i + 1].Coordinate - m_XReference)) / 2f;
                }
                else if ((dataFile.StableKeys[i].Coordinate > m_XReference) && (dataFile.StableKeys[i + 1].Coordinate > m_XReference))
                {
                    num += ((dataFile.StableKeys[i].Value + dataFile.StableKeys[i + 1].Value) * (dataFile.StableKeys[i + 1].Coordinate - dataFile.StableKeys[i].Coordinate)) / 2f;
                }
            }
            return (float)num;
        }
        private static double GetStableLineY(List<StableKeys> stableKeys, double XReference)
        {
            // 确保稳定键列表按 Coordinate 排序
            stableKeys = stableKeys.OrderBy(s => s.Coordinate).ToList();

            // 检查输入的 XReference 是否在数据的有效范围内
            if (XReference < stableKeys.First().Coordinate || XReference > stableKeys.Last().Coordinate)
            {
                throw new ArgumentOutOfRangeException("XReference", "The XReference is out of the range of the coordinates.");
            }

            // 遍历稳定键列表，找到与 XReference 相邻的两个点
            for (int i = 0; i < stableKeys.Count - 1; i++)
            {
                double x1 = stableKeys[i].Coordinate;
                double y1 = stableKeys[i].Value;
                double x2 = stableKeys[i + 1].Coordinate;
                double y2 = stableKeys[i + 1].Value;

                // 判断 XReference 是否在 x1 和 x2 之间
                if (XReference >= x1 && XReference <= x2)
                {
                    // 使用线性插值公式：Y = y1 + (X - x1) * (y2 - y1) / (x2 - x1)
                    double interpolatedY = y1 + (XReference - x1) * (y2 - y1) / (x2 - x1);
                    return interpolatedY;
                }
            }

            // 如果没有找到适合的区间，返回默认值或抛出异常
            throw new ArgumentException("XReference does not match any interval in the coordinate list.");
        }
        /*-----------------------------------------------------------------------------------------*/

        /// <summary>
        /// 获取轮廓左侧面积([MeasureKeys])。
        /// 
        /// </summary>
        private static float LeftMeasureArea(DataFile dataFile)
        {
            var m_XReference = dataFile.XReference;
            double num = 0f;

            for (int i = 0; i < (dataFile.MeasureKeys.Count - 1); i++)
            {
                if ((dataFile.MeasureKeys[i].Coordinate < m_XReference) && (dataFile.MeasureKeys[i + 1].Coordinate <= m_XReference))
                {
                    num += ((dataFile.MeasureKeys[i].Value + dataFile.MeasureKeys[i + 1].Value) * (dataFile.MeasureKeys[i + 1].Coordinate - dataFile.MeasureKeys[i].Coordinate)) / 2f;
                }
                else if ((dataFile.MeasureKeys[i].Coordinate < m_XReference) && (dataFile.MeasureKeys[i + 1].Coordinate > m_XReference))
                {
                    num += ((dataFile.MeasureKeys[i].Value + GetMeasureLineY(dataFile.MeasureKeys, m_XReference)) * (m_XReference - dataFile.MeasureKeys[i].Coordinate)) / 2f;
                }
            }
            return (float)num;
        }

        /// <summary>
        /// 获取轮廓右侧面积([MeasureKeys])。
        /// </summary>
        private static float RightMeasureArea(DataFile dataFile)
        {
            var m_XReference = dataFile.XReference;
            double num = 0f;
            for (int i = 0; i < (dataFile.MeasureKeys.Count - 1); i++)
            {
                if ((dataFile.MeasureKeys[i].Coordinate <= m_XReference) && (dataFile.MeasureKeys[i + 1].Coordinate > m_XReference))
                {
                    num += ((dataFile.MeasureKeys[i + 1].Value + GetMeasureLineY(dataFile.MeasureKeys, m_XReference)) * (dataFile.MeasureKeys[i + 1].Coordinate - m_XReference)) / 2f;
                }
                else if ((dataFile.MeasureKeys[i].Coordinate > m_XReference) && (dataFile.MeasureKeys[i + 1].Coordinate > m_XReference))
                {
                    num += ((dataFile.MeasureKeys[i].Value + dataFile.MeasureKeys[i + 1].Value) * (dataFile.MeasureKeys[i + 1].Coordinate - dataFile.MeasureKeys[i].Coordinate)) / 2f;
                }
            }
            return (float)num;
        }
        private static double GetMeasureLineY(List<MeasureKey> measureKeys, double XReference)
        {
            // 确保稳定键列表按 Coordinate 排序
            measureKeys = measureKeys.OrderBy(s => s.Coordinate).ToList();

            // 检查输入的 XReference 是否在数据的有效范围内
            if (XReference < measureKeys.First().Coordinate || XReference > measureKeys.Last().Coordinate)
            {
                throw new ArgumentOutOfRangeException("XReference", "The XReference is out of the range of the coordinates.");
            }

            // 遍历稳定键列表，找到与 XReference 相邻的两个点
            for (int i = 0; i < measureKeys.Count - 1; i++)
            {
                double x1 = measureKeys[i].Coordinate;
                double y1 = measureKeys[i].Value;
                double x2 = measureKeys[i + 1].Coordinate;
                double y2 = measureKeys[i + 1].Value;

                // 判断 XReference 是否在 x1 和 x2 之间
                if (XReference >= x1 && XReference <= x2)
                {
                    // 使用线性插值公式：Y = y1 + (X - x1) * (y2 - y1) / (x2 - x1)
                    double interpolatedY = y1 + (XReference - x1) * (y2 - y1) / (x2 - x1);
                    return interpolatedY;
                }
            }

            // 如果没有找到适合的区间，返回默认值或抛出异常
            throw new ArgumentException("XReference does not match any interval in the coordinate list.");
        }

        /// <summary>
        /// 获取轮廓左侧面积([Points])。
        /// 从序号1至mid，使用公式S左 =Σ((厚度n+厚度n-1)*0.03200341/2)
        /// </summary>
        private static float LeftMeasureArea_new(DataFile dataFile)
        {
            var m_XReference = dataFile.XReference;
            //计算中心点位置序号
            var mid = (int)(m_XReference / dataFile.FileInertvaWidth);
            double num = 0f;

            for (int i = 1; i < mid; i++)
            {
                var tmpValue = (dataFile.Points[i - 1].X + dataFile.Points[i].X) * dataFile.FileInertvaWidth / 2;
                num += tmpValue;
            }
            return (float)num;
        }

        /// <summary>
        /// 获取轮廓右面积实际值(Points)
        /// 从序号mid+1至末尾，使用公式S右 =Σ( (厚度n+厚度n-1)*0.03200341/2)
        /// </summary>
        private static float RightMeasureArea_new(DataFile dataFile)
        {
            var m_XReference = dataFile.XReference;
            //计算中心点位置序号
            var mid = (int)(m_XReference / dataFile.FileInertvaWidth);
            double num = 0f;

            for (int i = mid + 1; i < dataFile.Points.Count; i++)
            {
                var tmpValue = (dataFile.Points[i - 1].X + dataFile.Points[i].X) * dataFile.FileInertvaWidth / 2;
                num += tmpValue;
            }
            return (float)num;
        }
    }
}